package hub

import (
	"crypto/tls"
	"crypto/x509"
	"fmt"
	mqtt "github.com/eclipse/paho.mqtt.golang"
	"github.com/gogf/gf/database/gdb"
	"github.com/gogf/gf/encoding/gjson"
	"github.com/gogf/gf/frame/g"
	"github.com/gogf/gf/net/ghttp"
	"io/ioutil"
	"time"
)

func CreateMqttClient(cid string, onConnet mqtt.OnConnectHandler, onConnectionLost mqtt.ConnectionLostHandler) (client mqtt.Client) {
	opts := mqtt.NewClientOptions()
	opts.AddBroker(fmt.Sprintf("tcp://%s:%d", g.Cfg().GetString("mqtt.broker_url"), g.Cfg().GetInt("mqtt.broker_port")))
	opts.SetClientID(cid)
	//tlsconfig := newTLSConfig()
	//opts.SetTLSConfig(tlsconfig)
	opts.Username = g.Cfg().GetString("mqtt.broker_username")
	opts.Password = g.Cfg().GetString("mqtt.broker_pwd")
	opts.SetKeepAlive(60 * time.Second)
	opts.SetAutoReconnect(true) //当网络断开后，客户端会进行重连
	//opts.SetCleanSession(false)//把配置里的 cleanSession 设为false，客户端掉线后 服务器端不会清除session
	opts.ResumeSubs = true //SetResumeSubs将在连接时启用已存储(un)订阅消息的恢复功能，但如果CleanSession为false，则不会重新连接。
	// 设置消息回调处理函数
	//opts.SetDefaultPublishHandler(f)
	opts.OnConnect = onConnet
	opts.OnConnectionLost = onConnectionLost

	opts.SetPingTimeout(10 * time.Second)

	//opts.SetWill("offline",opts.ClientID+" offline",0,true)
	//opts.WillEnabled=true

	client = mqtt.NewClient(opts)
	return client
}
func newTLSConfig() *tls.Config {
	// Import trusted certificates from CAfile.pem.
	// Alternatively, manually add CA certificates to
	// default openssl CA bundle.
	certpool := x509.NewCertPool()

	pemCerts, err := ioutil.ReadFile("/file/MyRootCA.crt")
	if err == nil {
		certpool.AppendCertsFromPEM(pemCerts)
	}

	// Import client certificate/key pair
	cert, err := tls.LoadX509KeyPair("file/client.crt", "file/client.key")
	if err != nil {
		panic(err)
	}

	// Just to print out the client certificate..
	cert.Leaf, err = x509.ParseCertificate(cert.Certificate[0])
	if err != nil {
		panic(err)
	}
	//fmt.Println(cert.Leaf)
	//fmt.Println("NotAfter", cert.Leaf.NotAfter.String())

	// Create tls.Config with desired tls properties
	return &tls.Config{
		// RootCAs = certs used to verify server cert.
		RootCAs: certpool,
		// ClientAuth = whether to request cert from server.
		// Since the server is set up for SSL, this happens
		// anyways.
		ClientAuth: tls.RequireAndVerifyClientCert,
		// ClientCAs = certs used to validate client cert.
		ClientCAs: nil,
		// InsecureSkipVerify = verify that cert contents
		// match server. IP matches what is in cert etc.
		InsecureSkipVerify: true,
		// Certificates = list of certs client sends to server.
		Certificates: []tls.Certificate{cert},
	}
}

func GetApiClientsBak(params gdb.Map) (res []map[string]interface{}, count int) {
	client := ghttp.NewClient()
	client.SetBasicAuth(g.Cfg().GetString("mqtt.interface_user"), g.Cfg().GetString("mqtt.interface_pwd"))
	//client.SetContentType("none")
	url := g.Cfg().GetString("mqtt.interface_url") + ghttp.BuildParams(params)
	//g.Log().Line(true).Debugf("url:%s", url)
	resp, err := client.SetTimeout(20*time.Second).Get(url, nil)
	if err == nil {
		if resp.StatusCode == 200 {
			respStr := resp.ReadAllString()
			if json, err := gjson.DecodeToJson(respStr); err == nil {
				res = json.GetMaps("data")
				count = json.GetInt("meta.count")
			} else {
				g.Log().Line().Error(err)
			}
		} else {
			respStr := resp.ReadAllString()
			g.Log().Line(true).Debug("respStr : ", respStr, "resp.StatusCode:", resp.StatusCode)
		}
	}
	resp.Close() //要手动关闭，不然会内存泄漏
	return res, count
}

func GetApiClients(params gdb.Map) (res []map[string]interface{}, count int) {
	client := ghttp.NewClient()
	//client.SetBasicAuth(g.Cfg().GetString("mqtt.interface_user"), g.Cfg().GetString("mqtt.interface_pwd"))
	//client.SetContentType("none")
	client.SetHeader("Authorization", g.Cfg().GetString("mqtt.interface_token"))
	url := g.Cfg().GetString("mqtt.interface_url") + ghttp.BuildParams(params)
	//g.Log().Line(true).Debugf("url:%s", url)
	resp, err := client.SetTimeout(20*time.Second).Get(url, nil)
	if err == nil {
		if resp.StatusCode == 200 {
			respStr := resp.ReadAllString()
			if json, err := gjson.DecodeToJson(respStr); err == nil {
				res = json.GetMaps("data")
				count = json.GetInt("meta.count")
			} else {
				g.Log().Line().Error(err)
			}
		} else {
			respStr := resp.ReadAllString()
			g.Log().Line(true).Debug("respStr : ", respStr, "resp.StatusCode:", resp.StatusCode)
		}
	}
	resp.Close() //要手动关闭，不然会内存泄漏
	return res, count
}
